package org.oos.dao.lists;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.oos.atom.AtomEntity;
import org.oos.atom.AtomFeed;
import org.oos.dao.Dao;
import org.oos.dao.exceptions.DeleteException;
import org.oos.lists.DynamicList;
import org.oos.lists.SortableList;

public class RestoredDynamicList<Entity extends AtomEntity, Feed extends AtomFeed<Entity>>
		extends AbstractList<Entity> implements DynamicList<Entity>, SortableList<Entity> {
	private static final long serialVersionUID = -6311915954276862051L;

	protected List<Entity> buffer = new ArrayList<Entity>();
	protected Dao<Entity, Feed> dao;

	public RestoredDynamicList(Dao<Entity, Feed> dao, List<Entity> buffer) {
		super();
		this.buffer = buffer;
		this.dao = dao;
	}

	@Override
	public Entity get(int index) {
		return buffer.get(index);
	}

	@Override
	public int size() {
		return buffer.size();
	}

	@Override
	public List<Entity> getAll() {
		return buffer;
	}

	@Override
	public void loadAll() {
	}

	@Override
	public void add(int index, Entity element) {
		try {
			dao.create(element);
			buffer.add(index, element);
		} catch (Exception e) {
			dao.getLog().throwing(getClass().getSimpleName(),
					"add(int, Entity)", e);
			throw new RuntimeException(e);
		}
	}

	@Override
	public boolean add(Entity entity) {
		try {
			Entity newEntity = dao.create(entity);
			if (newEntity != null) {
				buffer.add(0, newEntity);
				return true;
			}
		} catch (Exception e) {
			dao.getLog().throwing(getClass().getSimpleName(), "add(Entity)", e);
			throw new RuntimeException(e);
		}
		return false;
	}

	@Override
	public Entity set(int index, Entity entity) {
		try {
			dao.update(entity);
			buffer.set(index, entity);
			return entity;
		} catch (Exception e) {
			dao.getLog().throwing(getClass().getSimpleName(),
					"set(int, Entity)", e);
			throw new RuntimeException(e);
		}
	}

	@Override
	public Entity remove(int index) {
		try {
			Entity entity = dao.read(index);
			dao.delete(entity);
			buffer.remove(entity);
			return entity;
		} catch (Exception e) {
			dao.getLog().throwing(getClass().getSimpleName(), "remove(Entity)",
					e);
			throw new RuntimeException(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public boolean remove(Object o) {
		try {
			return remove((Entity) o);
		} catch (ClassCastException e) {
			return super.remove(o);
		}
	}

	public boolean remove(Entity entity) {
		try {
			dao.delete(entity);
			buffer.remove(entity);
		} catch (DeleteException e) {
			throw new RuntimeException(e);
		}
		return super.remove(entity);
	}

	@SuppressWarnings("unchecked")
	@Override
	public RestoredDynamicList<Entity, Feed> clone()
			throws CloneNotSupportedException {
		return (RestoredDynamicList<Entity, Feed>) super.clone();
	}
	
	@Override
	public void sort(Comparator<Entity> comparator) {
		Collections.sort(this.buffer, comparator);
	}
}
